package com.systemCapacity.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.systemCapacity.common.dto.BattleCapacityDto;
import com.systemCapacity.common.dto.BattleCapacityResolveDto;
import com.systemCapacity.common.dto.CapacityMenuDto;
import com.systemCapacity.common.dto.SimplifiedCapacityDto;
import com.systemCapacity.entity.BattleCapacity;
import com.systemCapacity.entity.BattleCapacityResolve;
import com.systemCapacity.entity.Enum.TenCapacityType;
import com.systemCapacity.mapper.BattleCapacityResolveMapper;
import com.systemCapacity.service.BattleCapacityResolveService;
import com.systemCapacity.service.BattleCapacityService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class BattleCapacityResolveServiceImpl extends ServiceImpl<BattleCapacityResolveMapper, BattleCapacityResolve>
        implements BattleCapacityResolveService {

    @Autowired
    BattleCapacityResolveMapper battleCapacityResolveMapper;

    @Autowired
    BattleCapacityService battleCapacityService;

    private static final String digitStr = "^[-\\+]?[\\d]*$";

    @Override
    public List<BattleCapacityResolveDto> getTree() {
        List<BattleCapacityResolveDto> dtos = new ArrayList<>();
        for (TenCapacityType type : TenCapacityType.values()) {
            BattleCapacityResolveDto dto = new BattleCapacityResolveDto();
            dto.setCapacityId(String.valueOf(type.getValue()));
            dto.setCapacityName(type.getDes());
            dtos.add(dto);
            dto.setCapacityType(type);
            List<BattleCapacityDto> capacities = battleCapacityService.getBattleCapacities(dto.getCapacityType().getValue(), "");
            dto.setChildCapacities(capacities.stream().map(this::transferCapacityToResolve).collect(Collectors.toList()));
        }
        return dtos;
    }

    /**
     * 查询作战任务下的能力分解
     * @param taskId 作战id
     * @return 能力分解树
     */
    @Override
    public List<String> getResolve(String taskId) {
        // 先添加十大能力
        List<String> ids = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        QueryWrapper<BattleCapacityResolve> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("taskId", taskId);
        battleCapacityResolveMapper.selectList(queryWrapper).forEach(resolve -> ids.add(resolve.getCapacityId()));
        return ids;
    }

    /**
     * 查询作战任务下的能力分解
     *
     * @param taskId 作战id
     * @return 能力分解树
     */
    @Override
    public List<BattleCapacityResolveDto> getResolveCapacityList(String taskId) {
        QueryWrapper<BattleCapacityResolve> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("taskId", taskId);
        queryWrapper.and(q -> q.isNull("pid")
                .or()
                .eq("pid",""));
        List<BattleCapacityResolve> battleCapacityResolveList = battleCapacityResolveMapper.selectList(queryWrapper);
        battleCapacityResolveList = battleCapacityResolveList.stream().filter(x -> !x.getCapacityId().equals(String.valueOf(x.getCapacityType().getValue()))).collect(Collectors.toList());
        List<BattleCapacityResolveDto> capacityDtoList = battleCapacityResolveList.stream().map(x -> {
            BattleCapacityResolveDto dto = new BattleCapacityResolveDto();
            BeanUtils.copyProperties(x,dto);
            return dto;
        }).collect(Collectors.toList());
        //查询子能力
        for (BattleCapacityResolveDto capacityDto : capacityDtoList) {
            QueryWrapper<BattleCapacityResolve> queryChildRen = new QueryWrapper<>();
            queryChildRen.eq("pid",capacityDto.getCapacityId());
            queryChildRen.eq("taskId",taskId);
            List<BattleCapacityResolve> childResoveList = battleCapacityResolveMapper.selectList(queryChildRen);
            List<BattleCapacityResolveDto> childCapacityList = childResoveList.stream().map(x -> {
                BattleCapacityResolveDto child = new BattleCapacityResolveDto();
                BeanUtils.copyProperties(x,child);
                return child;
            }).collect(Collectors.toList());
            capacityDto.setChildCapacities(childCapacityList);
        }
        return capacityDtoList;
    }

    /**
     * 查询十大能力下的子能力
     * @param taskId 作战任务
     * @param capacityType 十大能力
     * @return 十大能力分解树
     */
    @Override
    public List<BattleCapacityResolveDto> getChildResolve(String taskId, TenCapacityType capacityType) {
        // 查询十大能力下的分解子能力
        LambdaQueryWrapper<BattleCapacityResolve> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BattleCapacityResolve::getCapacityType, capacityType.getValue());
        lambdaQueryWrapper.eq(BattleCapacityResolve::getTaskId, taskId);
        lambdaQueryWrapper.eq(BattleCapacityResolve::getCapacityType, capacityType.getValue());
        lambdaQueryWrapper.ne(BattleCapacityResolve::getCapacityId, String.valueOf(capacityType.getValue()));
//        lambdaQueryWrapper.is(BattleCapacityResolve::getPid);
        List<BattleCapacityResolve> resolves = battleCapacityResolveMapper.selectList(lambdaQueryWrapper);
        List<BattleCapacityResolveDto> dtos = new ArrayList<>();
        for (BattleCapacityResolve resolve : resolves) {
            BattleCapacityResolveDto dto = new BattleCapacityResolveDto();
            dto.setResolveId(resolve.getResolveId());
            dto.setCapacityId(resolve.getCapacityId());
            dto.setCapacityName(resolve.getCapacityName());
            dto.setTaskId(resolve.getTaskId());
            dto.setCapacityType(resolve.getCapacityType());
            // 查询二级子能力
            LambdaQueryWrapper<BattleCapacityResolve> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BattleCapacityResolve::getPid, resolve.getResolveId());
            List<BattleCapacityResolve> battleCapacityResolves = battleCapacityResolveMapper.selectList(queryWrapper);
            List<BattleCapacityResolveDto> childDtos = battleCapacityResolves.stream()
                    .map(resolve1 -> BeanUtil.copyProperties(resolve1, BattleCapacityResolveDto.class))
                    .collect(Collectors.toList());
            dto.setChildCapacities(childDtos);
            dtos.add(dto);
        }
        return dtos;
    }

    @Override
    public boolean resolveExist(String resolveId) {
        LambdaQueryWrapper<BattleCapacityResolve> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BattleCapacityResolve::getResolveId, resolveId);
        return getOne(lambdaQueryWrapper) != null;
    }

    /**
     * 保存作战能力分解树
     * @param dtos 作战能力分解结构
     */
    @Override
    public void addBattleResolve(List<BattleCapacityResolveDto> dtos) {
        // 最外层是十大能力，十大能力复用
        for (BattleCapacityResolveDto dto : dtos) {
            // 十大能力列表
            List<BattleCapacityResolveDto> capacityResolveDtos = dto.getChildCapacities();
            for (BattleCapacityResolveDto childResolveDto : capacityResolveDtos) {
                saveBattleResolve(childResolveDto, "");
            }
        }
    }

    @Override
    public void deleteResolve(String taskId) {
        QueryWrapper<BattleCapacityResolve> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("taskId", taskId);
        remove(queryWrapper);
    }

    @Override
    @Transactional
    public boolean addBattleResolveByIds(List<String> ids, String taskId) {
        Pattern pattern = Pattern.compile(digitStr);
        ids.forEach(id -> {
            if (pattern.matcher(id).matches()) {
                // 是十大能力
                BattleCapacityResolve resolve = new BattleCapacityResolve();
                resolve.setResolveId(UUID.randomUUID().toString());
                resolve.setCapacityId(id);
                resolve.setCapacityName(TenCapacityType.values()[Integer.parseInt(id)].getDes());
                resolve.setTaskId(taskId);
                resolve.setCapacityType(TenCapacityType.values()[Integer.parseInt(id)]);
                save(resolve);
            } else if (battleCapacityService.capacityExist(id)) {
                BattleCapacity capacity = battleCapacityService.getById(id);
                BattleCapacityResolve resolve = BeanUtil.copyProperties(capacity, BattleCapacityResolve.class);
                resolve.setTaskId(taskId);
                resolve.setResolveId(UUID.randomUUID().toString());
                save(resolve);
            }
        });
        return true;
    }

    public  void saveBattleResolve(BattleCapacityResolveDto dto, String pid) {
        BattleCapacityResolve resolve = new BattleCapacityResolve();
        resolve.setResolveId(UUID.randomUUID().toString());
        resolve.setCapacityId(dto.getCapacityId());
        resolve.setCapacityName(dto.getCapacityName());
        resolve.setCapacityType(dto.getCapacityType());
        resolve.setTaskId(dto.getTaskId());
        if (pid != null && !pid.isEmpty()) {
            resolve.setPid(pid);
        } else {
            resolve.setPid(resolve.getCapacityType().getValue().toString());
        }
        save(resolve);
        for (BattleCapacityResolveDto childDto : dto.getChildCapacities()) {
            saveBattleResolve(childDto, resolve.getResolveId());
        }
    }

    public BattleCapacityResolveDto transferCapacityToResolve(BattleCapacityDto battleCapacityDto) {
        BattleCapacityResolveDto dto = new BattleCapacityResolveDto();
        dto.setCapacityId(battleCapacityDto.getCapacityId());
        dto.setCapacityName(battleCapacityDto.getCapacityName());
        dto.setCapacityType(battleCapacityDto.getCapacityType());
        List<BattleCapacityDto> children = battleCapacityDto.getChildren();
        if (children != null) {
            List<BattleCapacityResolveDto> child = children.stream()
                    .map(this::transferCapacityToResolve).collect(Collectors.toList());
            dto.setChildCapacities(child);
        } else {
            dto.setChildCapacities(new ArrayList<>());
        }
        return dto;
    }

    @Override
    public List<CapacityMenuDto> getCapacitiesMenu(String taskId) {
        List<CapacityMenuDto> dtos = new ArrayList<>();
        for (TenCapacityType type : TenCapacityType.values()) {
            QueryWrapper<BattleCapacityResolve> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("capacityId", String.valueOf(type.getValue()));
            queryWrapper.eq("taskId", taskId);
            if (getOne(queryWrapper) == null) {
                continue;
            }
            CapacityMenuDto dto = new CapacityMenuDto();
            dtos.add(dto);
            dto.setTenCapacityType(type);
            dto.setChildren(new ArrayList<>());
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("capacityType", type.getValue());
            queryWrapper.ne("capacityId", String.valueOf(type.getValue()));
            queryWrapper.eq("taskId", taskId);
            List<BattleCapacityResolve> resolves = battleCapacityResolveMapper.selectList(queryWrapper)
                    .stream().filter(battleCapacityResolve -> battleCapacityResolve.getPid().isEmpty())
                    .collect(Collectors.toList());
            for (BattleCapacityResolve resolve : resolves) {
                SimplifiedCapacityDto capacityDto = BeanUtil.copyProperties(resolve, SimplifiedCapacityDto.class);
                dto.getChildren().add(capacityDto);
                capacityDto.setChildren(new ArrayList<>());
                QueryWrapper<BattleCapacityResolve> resolveQueryWrapper = new QueryWrapper<>();
                resolveQueryWrapper.eq("pid", resolve.getCapacityId());
                resolveQueryWrapper.eq("taskId", taskId);
                battleCapacityResolveMapper.selectList(resolveQueryWrapper)
                        .forEach(battleCapacityDto -> capacityDto.getChildren()
                                .add(BeanUtil.copyProperties(battleCapacityDto, SimplifiedCapacityDto.class)));
            }
        }
        return dtos;
    }
}
